package reuse

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/jlaffaye/ftp"
)

// 站点配置
type SiteConfig struct {
	Name string `json:"name"`
	// todo: maybe more clear what type, because Type usually damn the world
	Type     string `json:"type"`
	Host     string `json:"host"`
	Port     string `json:"port"`
	Account  string `json:"account"`
	Password string `json:"password"`
}

// 配置文件go-tuiftp需要
type SysConfig struct {
	Sites []SiteConfig `json:"sites"` // 站点列表
}

type FtpClient struct {
	Conn *ftp.ServerConn
}

// app名称
var AppName = "go-tuiftp"

// todo: when using go-releaser do version ?
var AppVersion = "v0.0.1"

// ftp连接超时
var FtpTimeout = 5 * time.Second

// 为了调试
var DebugMode = true

// 获取配置文件路径
func GetConfigPath() (string, error) {
	home, err := os.UserHomeDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(home, AppName+".json"), nil
}

// 在reuse包中添加创建配置文件的函数
func EnsureConfigFileExists() error {
	configPath, err := GetConfigPath()
	if err != nil {
		return err
	}

	// 检查文件是否存在
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		// 创建空的配置文件
		sysConfig := &SysConfig{
			Sites: []SiteConfig{}, // 初始化空的站点列表
		}
		// 保存空配置到文件
		return sysConfig.Save()
	}
	return err
}

// Read 读取配置文件
func (in *SysConfig) Read() error {
	// 确保配置文件存在
	if err := EnsureConfigFileExists(); err != nil {
		return err
	}

	configPath, err := GetConfigPath()
	if err != nil {
		return err
	}

	configContent, err := os.ReadFile(configPath)
	if err != nil {
		return err
	}

	return json.Unmarshal(configContent, in)
}

// Save 保存配置文件
func (in *SysConfig) Save() error {
	configPath, err := GetConfigPath()
	if err != nil {
		return err
	}
	// parse the config file
	configContent, err := json.Marshal(in)
	if err != nil {
		return err
	}
	// write the config file
	err = os.WriteFile(configPath, configContent, 0644)
	if err != nil {
		return err
	}
	return nil
}

// NewFtpClient 创建ftp客户端
func NewFtpClient(site SiteConfig) (*FtpClient, error) {
	conn, err := ftp.Dial(site.Host+":"+site.Port, ftp.DialWithTimeout(FtpTimeout))
	if err != nil {
		return nil, err
	}
	err = conn.Login(site.Account, site.Password)
	if err != nil {
		return nil, err
	}
	return &FtpClient{Conn: conn}, nil
}

// HumanReadableSize 格式化文件大小
func HumanReadableSize(size uint64) string {
	const (
		B  = 1
		KB = 1024 * B
		MB = 1024 * KB
		GB = 1024 * MB
	)
	switch {
	case size >= GB:
		return fmt.Sprintf("%.2f GB", float64(size)/float64(GB))
	case size >= MB:
		return fmt.Sprintf("%.2f MB", float64(size)/float64(MB))
	case size >= KB:
		return fmt.Sprintf("%.2f KB", float64(size)/float64(KB))
	default:
		return fmt.Sprintf("%d B", size)
	}
}

// how to use log file??
func Log(msg string) {
	LogIntoFile(msg, os.Stdout)
}
func LogIntoFile(msg string, file *os.File) {
	file.Write([]byte(msg))
}

func If[T any](condition bool, a, b T) T {
	if condition {
		return a
	}
	return b
}
